package com.parsec.sb.practice;

import com.parsec.sb.entity.User;

import java.util.*;
import java.util.stream.Collectors;

public class StreamPractice {

    public static List<User> userList = new ArrayList<>();

    static {
        userList.add(User.builder().name("Tom").age(21).salary(8900).build());
        userList.add(User.builder().name("Jack").age(24).salary(7000).build());
        userList.add(User.builder().name("Lily").age(19).salary(7800).build());
        userList.add(User.builder().name("Anni").age(28).salary(8200).build());
        userList.add(User.builder().name("Owen").age(26).salary(9500).build());
        userList.add(User.builder().name("Alisa").age(32).salary(7900).build());
    }

    public static void main(String[] args) {
//        test1();
//        test2();
//        test3();
//        test4();
//        testReduce();
        testFlatMap();
    }

    public static void testReduce() {
        List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
        // 求和方式1
        Optional<Integer> sum1 = list.stream().reduce((x, y) -> x + y);
        // 求和方式2
        Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
        // 求和方式3
        Integer sum3 = list.stream().reduce(0, Integer::sum);

        // 求乘积
        Optional<Integer> product = list.stream().reduce((x, y) -> x * y);

        // 求最大值方式1
        Optional<Integer> max1 = list.stream().reduce((x, y) -> x > y ? x : y);
        // 求最大值写法2
        Integer max2 = list.stream().reduce(1, Integer::max);

        System.out.println("list求和：" + sum1.get() + "," + sum2.get() + "," + sum3);
        System.out.println("list求积：" + product.get());
        System.out.println("list求最大值：" + max1.get() + "," + max2);

        Integer maxSalary = userList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(),
                Integer::max);
        Integer sumSalary = userList.stream().reduce(0, (sum, p) -> sum += p.getSalary(), Integer::sum);
        System.out.println("最高工资为：" + maxSalary);
        System.out.println("所有人工资和为：" + sumSalary);
    }

    /**
     * https://www.cnblogs.com/maohuidong/p/14072565.html
     * map只是一维 1对1 的映射
     * flatmap可以将一个2维的集合映射成一个一维,相当于他映射的深度比map深了一层
     */
    public static void testFlatMap() {
        //对给定单词列表 ["Hello","World"],你想返回列表["H","e","l","o","W","r","d"]
        String[] words = new String[]{"Hello", "World"};
        Arrays.stream(words)
                .map(word -> word.split(""))
                .distinct()
                .collect(Collectors.toList())
                .forEach(System.out::println);
        Arrays.stream(words)
                .map(word -> word.split(""))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(Collectors.toList())
                .forEach(System.out::println);
    }

    /**
     * foreach
     * findFirst
     * findAny
     * anyMatch
     */
    public static void test1() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);

        // 遍历输出符合条件的元素
        list.stream().filter(x -> x > 6).forEach(System.out::println);
        // 匹配第一个
        Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
        // 匹配任意（适用于并行流）
        Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
        // 是否包含符合特定条件的元素
        boolean anyMatch = list.stream().anyMatch(x -> x > 6);
        System.out.println("匹配第一个值：" + findFirst.get());
        System.out.println("匹配任意一个值：" + findAny.get());
        System.out.println("是否存在大于6的值：" + anyMatch);
    }

    /**
     * filter
     * map
     * collect
     */
    public static void test2() {
        List<String> filterList = userList.stream().filter(x -> x.getSalary() > 8000)
                .map(User::getName).collect(Collectors.toList());
        System.out.println("高于8000的员工姓名：" + filterList);
    }

    /**
     * max
     * min
     * count
     */
    public static void test3() {
        Optional<User> maxSalary = userList.stream().max(Comparator.comparingInt(User::getSalary));
        Optional<User> minAge = userList.stream().max((u1, u2) -> -u1.getAge().compareTo(u2.getAge()));
        Optional<User> minAge2 = userList.stream().max((u1, u2) -> u2.getAge().compareTo(u1.getAge()));
        long count = userList.stream().filter(x -> x.getSalary() > 8000).count();
        System.out.println("最高工资为：" + maxSalary);
        System.out.println("最低年龄为：\n" + minAge + ",\n" + minAge2);
        System.out.println("工资高于8000的人数：" + count);
    }

    public static void test4() {
        System.out.println(userList);
        List<User> list = userList.stream().map(user -> {
            user.setName(user.getName().toUpperCase());
            user.setAge(user.getAge() + 1);
            user.setSalary(user.getSalary() + 1000);
            return user;
        }).collect(Collectors.toList());
        System.out.println(list);
    }

}

